package com.cqupt.scanning.system.acl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqupt.scanning.handler.exception.MyException;
import com.cqupt.scanning.system.acl.entity.AclRole;
import com.cqupt.scanning.system.acl.entity.AclUser;
import com.cqupt.scanning.system.acl.entity.AclUserRole;
import com.cqupt.scanning.system.acl.entity.dto.UserDTO;
import com.cqupt.scanning.system.acl.entity.vo.UserVO;
import com.cqupt.scanning.system.acl.mapper.AclUserMapper;
import com.cqupt.scanning.system.acl.service.AclRoleService;
import com.cqupt.scanning.system.acl.service.AclUserRoleService;
import com.cqupt.scanning.system.acl.service.AclUserService;
import com.cqupt.scanning.system.utils.common.PasswordEncryption;
import com.cqupt.scanning.system.utils.result.R;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 宋宝梁
 * @since 2021-07-05
 */
@Service
public class AclUserServiceImpl extends ServiceImpl<AclUserMapper, AclUser> implements AclUserService {

    private AclUserRoleService aclUserRoleService;
    private AclRoleService aclRoleService;

    @Autowired
    public AclUserServiceImpl(AclUserRoleService aclUserRoleService, AclRoleService aclRoleService) {
        this.aclUserRoleService = aclUserRoleService;
        this.aclRoleService = aclRoleService;
    }

    @Override
    public AclUser selectByUsername(String username) {
        return baseMapper.selectOne(new QueryWrapper<AclUser>().eq("username", username));
    }

    @Override
    public R getAllAdmin(Page<AclUser> page, String query) {
        IPage<AclUser> aclUserIPage = baseMapper.selectPage(page, new QueryWrapper<AclUser>().like("username", query));
        List<AclUser> records = aclUserIPage.getRecords();
        List<UserDTO> users = new ArrayList<>();
        for (AclUser record : records) {
            UserDTO userDTO = new UserDTO();
            if(record.getNote().equals("1")) {
                BeanUtils.copyProperties(record, userDTO);
                users.add(userDTO);
            }
        }
        return R.ok().data("users", users).data("total", users.size());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public R addUser(UserVO userVO) {
        try {
            Integer count = baseMapper.selectCount(new QueryWrapper<AclUser>().eq("username", userVO.getUsername()));
            if (count >= 1) return R.error().message("username is used");
            AclRole role = aclRoleService.getById(userVO.getRoleId());
            AclUser aclUser = new AclUser();
            BeanUtils.copyProperties(userVO, aclUser);
            aclUser.setPassword(PasswordEncryption.execute(userVO.getPassword().trim()));
            aclUser.setNote("1");
            aclUser.setType(role.getRoleName());
            baseMapper.insert(aclUser);
            AclUserRole userRole = new AclUserRole();
            userRole.setUserId(aclUser.getId()).setRoleId(userVO.getRoleId());
            aclUserRoleService.save(userRole);
            return R.ok();
        } catch (Exception e) {
            e.getStackTrace();
            throw new MyException(20001, "Add failed");
        }
}

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public R updateUser(UserDTO userDTO, Integer roleId) {
        try {
            AclUser aclUser = new AclUser();
            BeanUtils.copyProperties(userDTO, aclUser);
            aclUser.setPassword(PasswordEncryption.execute(userDTO.getPassword().trim()));
            baseMapper.updateById(aclUser);
            AclUserRole aclUserRole = aclUserRoleService.getOne(new QueryWrapper<AclUserRole>().eq("user_id", aclUser.getId()));
            aclUserRole.setRoleId(roleId);
            aclUserRoleService.update(aclUserRole, new QueryWrapper<AclUserRole>().eq("user_id", aclUser.getId()));
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(20001, "修改失败,请重新尝试");
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public R removeUserById(Integer userId) {
        try {
            baseMapper.deleteById(userId);
            aclUserRoleService.remove(new QueryWrapper<AclUserRole>().eq("user_id", userId));
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(20001, "Remove failed");
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public R assignRole(Integer userId, Integer roleId) {
        try {
            AclRole role = aclRoleService.getById(roleId);
            AclUser user = new AclUser();
            user.setType(role.getRoleName()).setId(userId);
            baseMapper.updateById(user);
            AclUserRole userRole = new AclUserRole();
            userRole.setRoleId(roleId).setUserId(userId);
            aclUserRoleService.save(userRole);
            return R.ok();
        } catch (Exception e) {
            e.getStackTrace();
            throw new MyException(20001, "Role assignment failed");
        }
    }

    @Override
    public R getOneUser(Integer userId) {
        AclUser aclUser = baseMapper.selectById(userId);
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(aclUser, userDTO);
        return R.ok().data("user", userDTO);
    }
}
